/* 
 * File:   MementoCaretaker.cpp
 * Author: Gab'z
 * 
 * Created on 25 mai 2012, 17:53
 */

#include <sstream>

#include "MementoCaretaker.h"
#include "exception/MementoException.h"

namespace calculator {
    Logger* MementoCaretaker::log = LoggerManager::getInstance()->getLogger("MementoCaretaker");

    MementoCaretaker* MementoCaretaker::instance = 0;

    MementoCaretaker::MementoCaretaker() {
        _iteratorCurrentMemento = _mementoList.begin();
    }

    //    MementoCaretaker::MementoCaretaker(const MementoCaretaker& orig) : _mementoList(orig._mementoList) {
    //        _iteratorCurrentMemento = _mementoList.begin();
    //    }

    MementoCaretaker::~MementoCaretaker() {
        log->trace("deleting Memento...");
        for (std::list<const Memento*>::iterator it = _mementoList.begin();
                it != _mementoList.end();
                it++) {
            delete *it;
        }
        _mementoList.clear();
        log->trace("deleting Memento done");
    }

    // supprime les memento suivants
    // ajoute celui passé en paramètre à la fin

    unsigned int MementoCaretaker::getCurrentMementoIndex() const {
        unsigned int index = 0;
        std::list<const Memento*>::const_iterator it = _mementoList.begin();
        while (it != _iteratorCurrentMemento) {
            it++;
            index++;
        }
        return index;
    }

    void MementoCaretaker::addMemento(const Memento* memento) {
        log->trace("AddMemento");
        if (_iteratorCurrentMemento != _mementoList.end()) cutMementoList();
        _mementoList.push_back(memento);
        // _iteratorCurrentMemento++;
        _iteratorCurrentMemento = _mementoList.end();

        std::ostringstream oss;
        oss << "Memento stored : " << _mementoList.size() << " memento in memory, current index is " << getCurrentMementoIndex();
        log->trace(oss.str());
    }

    void MementoCaretaker::cutMementoList() {
        log->trace("CutMementoList");
        std::list<const Memento*>::iterator it = _iteratorCurrentMemento;
        it++;
        for (; it != _mementoList.end(); it++) {
            delete *it;
        }
        it = _iteratorCurrentMemento;
        it++;
        _mementoList.erase(it, _mementoList.end());
    }

    std::string MementoCaretaker::getPreviousInputString() const {
        if (!hasPrevious()) return "";
        std::list<const Memento*>::const_iterator it = _iteratorCurrentMemento;
        it--;
        return (*it)->getInputString();
    }

    bool MementoCaretaker::hasPrevious() const {
        return (_iteratorCurrentMemento != _mementoList.begin());
    }

    bool MementoCaretaker::hasNext() const {
        return (_iteratorCurrentMemento != _mementoList.end());
    }

    void MementoCaretaker::goPrevious() throw (MementoException) {
        if (!hasPrevious()) throw MementoException("No previous Memento");
        else _iteratorCurrentMemento--;
    }

    void MementoCaretaker::goNext() throw (MementoException) {
        if (!hasNext()) throw MementoException("No next Memento");
        else _iteratorCurrentMemento++;
    }

    const Memento* MementoCaretaker::getPreviousMemento() const throw (MementoException) {
        if (!hasPrevious()) throw MementoException("No previous Memento");
        std::list<const Memento*>::const_iterator it = _iteratorCurrentMemento;
        it--;
        return *it;
    }

    const Memento* MementoCaretaker::getNextMemento() const throw (MementoException) {
        if (!hasNext()) throw MementoException("No next Memento");
        std::list<const Memento*>::const_iterator it = _iteratorCurrentMemento;
        return *it;
    }
}
